package cc.rboot.inject.resolver;

import cc.rboot._core.helper.RequestHelper;
import cc.rboot.inject.annotation.InjectBody;
import cc.rboot.inject.helper.InjectSetterHelper;
import cc.rboot.inject.helper.InjectValidateHelper;
import cc.rboot.inject.core.InjectConstant;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

@Component
public class InjectBodyResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(InjectBody.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {

        /**
         * 获取Inject类中的泛型EntityClass
         * 此处是通过InjectInterceptor拦截器注入的
         */
        Class entityClass = (Class) nativeWebRequest.getAttribute(InjectConstant.INJECT_ENTITY, RequestAttributes.SCOPE_REQUEST);

        if (entityClass == null) {
            throw new Exception("InjectBody仅支持IFather的子类");
        }
        /**
         * 转化RequestBody
         */
        Object entity = RequestHelper.getRequestBody(entityClass);

        /**
         * 有InjectSetter则注入默认值
         */
        if (InjectSetterHelper.supportsInjectDefault(methodParameter)) {
            InjectSetterHelper.injectSetter(entity);
        }

        /**
         * 手动校验
         */
        if (InjectValidateHelper.supportsValidate(methodParameter)) {
            InjectValidateHelper.validate(entity);
        }

        return entity;
    }
}

